package com.itc.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itc.common.core.domain.R;
import com.itc.common.core.utils.SpringUtils;
import com.itc.common.core.utils.StringUtils;
import com.itc.common.security.utils.SecurityUtils;
import com.itc.system.api.domain.SysDept;
import com.itc.system.api.domain.SysUser;
import com.itc.system.api.domain.dto.SysDeptCheckDto;
import com.itc.system.domain.SysDeptMenu;
import com.itc.system.domain.dto.SysDeptMenuDto;
import com.itc.system.domain.vo.TreeSelectDept;
import com.itc.system.mapper.SysDeptMapper;
import com.itc.system.service.SysDeptMenuService;
import com.itc.system.service.SysDeptService;
import com.itc.system.service.SysUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author wangjinxia
* @description 针对表【sys_dept(部门表)】的数据库操作Service实现
* @createDate 2024-05-10 15:53:30
*/
@Service
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept>
    implements SysDeptService{

    @Autowired
    private SysDeptMenuService sysDeptMenuService;

    @Autowired
    private SysUserService sysUserService;

    /**
     * 添加部门
     * @param sysDept
     * @return
     */
    @Override
    public R addDept(SysDept sysDept) {
        //只能在部门下新增
        SysDept parentDept = this.baseMapper.selectById(sysDept.getParentId());
        if(parentDept == null){
            return R.fail("父节点信息异常");
        }
        if(parentDept.getDeptType().intValue() != 1){
            return R.fail("席位下不允许新增部门/席位");
        }

        //查询用部门或席位是否存在
        Long count=this.baseMapper.selectCount(new LambdaQueryWrapper<SysDept>()
                .eq(SysDept::getDeptName,sysDept.getDeptName())
                .eq(SysDept::getDelFlag,0)
        );
        if (count>0){
           return R.fail("部门或席位已存在！！！");
        }
        // 获取父级部门的祖先部门信息，并将当前部门的 ID 加入其中
        String ancestors = parentDept.getAncestors() + "," + sysDept.getParentId();
        // 将fu部门信息赋值给当前部门
        sysDept.setAncestors(ancestors);

        // 设置显示顺序
        Integer deptCount = this.baseMapper.selectCount(new LambdaQueryWrapper<SysDept>()
                .eq(SysDept::getParentId, sysDept.getParentId())
        ).intValue();
        sysDept.setOrderNum(deptCount + 1);

        // 设置其他属性
        sysDept.setLeader(SecurityUtils.getUsername());
        sysDept.setStatus("0");
        sysDept.setDelFlag("0");
        sysDept.setCreateBy(SecurityUtils.getUsername());
        sysDept.setCreateTime(LocalDate.now().toString());
        this.save(sysDept);

        if(sysDept.getMenuIds() != null && sysDept.getMenuIds().size() > 0){
            SysDeptMenuDto dto = new SysDeptMenuDto();
            dto.setDeptId(sysDept.getDeptId());
            dto.setMenuIds(sysDept.getMenuIds());
            this.menuBind(dto);
        }
        return R.ok() ;
    }

    @Override
    public R removeDept(Long deptId) {
        SysDept sysDept = this.baseMapper.selectById(deptId);
        if(sysDept == null){
            return R.fail("部门/席位信息异常");
        }

        //校验是否有下级部门，如果有，则不允许删除
        Long count = this.baseMapper.selectCount(
                new LambdaQueryWrapper<SysDept>()
                .like(SysDept::getAncestors,deptId)
                .eq(SysDept::getDelFlag,"0")
        );
        if(count > 0){
            return R.fail("请先删除下级部门/席位");
        }

        sysDept.setDelFlag("2");
        this.updateById(sysDept);
        return R.ok();
    }


    @Override
    public R getDetail(Long deptId) {
        SysDept sysDept = this.baseMapper.selectById(deptId);
        if(sysDept == null){
            return R.fail("部门/席位信息异常");
        }
        List<SysDeptMenu> deptMenuList = sysDeptMenuService.getBaseMapper().selectList(
                new LambdaQueryWrapper<SysDeptMenu>()
                .eq(SysDeptMenu::getDeptId,deptId)
        );
        if(deptMenuList.size() > 0){
            sysDept.setMenuIds(deptMenuList.stream().map(SysDeptMenu::getMenuId).collect(Collectors.toList()));
        }
        return R.ok(sysDept);
    }

    @Override
    @Transactional
    public R menuBind(SysDeptMenuDto dto) {
        if(dto.getMenuIds().size() == 0){
            return R.fail("权限信息不能为空");
        }
        SysDept sysDept = this.baseMapper.selectById(dto.getDeptId());
        if(sysDept == null){
            return R.fail("席位信息异常");
        }
//        if(sysDept.getDeptType().intValue() != 2){
//            return R.fail("只能对席位进行权限绑定");
//        }

        //先删除再新增
        sysDeptMenuService.getBaseMapper().delete(
                new LambdaQueryWrapper<SysDeptMenu>()
                .eq(SysDeptMenu::getDeptId,sysDept.getDeptId())
        );

        List<SysDeptMenu> saveList = new LinkedList<>();
        for (Long menuId : dto.getMenuIds()) {
            SysDeptMenu sysDeptMenu = new SysDeptMenu();
            sysDeptMenu.setDeptId(sysDept.getDeptId());
            sysDeptMenu.setMenuId(menuId);
            saveList.add(sysDeptMenu);
        }
        if(saveList.size() > 0){
            sysDeptMenuService.saveBatch(saveList);
        }

        return R.ok();
    }

    //根据id获取部门数据
    @Override
    public List<SysDept> getSysDeptById(String deptIds) {
        List<Long> collect = Arrays.stream(deptIds.split(",")).map(Long::parseLong).collect(Collectors.toList());
        return this.baseMapper.selectBatchIds(collect);
    }



    @Override
    public SysUser getUserById(Long userId) {
        LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysUserLambdaQueryWrapper.eq(SysUser::getUserId,userId);
        sysUserLambdaQueryWrapper.last("limit 1");
        SysUser one = sysUserService.getOne(sysUserLambdaQueryWrapper);
        if (one != null){
            return one;
        }
        throw new NullPointerException("数据不存在");
    }

    @Override
    public SysDept getDeptById(Long deptId) {
        LambdaQueryWrapper<SysDept> sysDeptLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysDeptLambdaQueryWrapper.eq(SysDept::getDeptId,deptId);
        sysDeptLambdaQueryWrapper.last("limit 1");
        return this.baseMapper.selectOne(sysDeptLambdaQueryWrapper);
    }

    @Override
    public List<SysDept> getDeptChildByUserIds(String deptChildId) {
        return Arrays.stream(deptChildId.split(","))
                .map(id -> this.baseMapper.selectById(Long.parseLong(id)))
                .collect(Collectors.toList());
    }

    @Override
    public Boolean biDeptCheck(SysDeptCheckDto dto) {
        Boolean result = false;
        if(dto.getUserId() == null || dto.getDeptIds() == null || dto.getDeptIds().size() == 0){
            return result;
        }
        if(SecurityUtils.isAdmin(dto.getUserId())){
            return true;
        }
        SysUser user = sysUserService.getBaseMapper().selectById(dto.getUserId());
        if(user == null){
            return result;
        }
        //所有校验都通过最底层的席位去判断，只要有其中一个席位即表示有权限
        List<Long> checkSeatIds = this.baseMapper.getSeatIdsByDeptIds(dto.getDeptIds());

        //获取用户有权限的所有席位信息
        List<Long> seatIds = new LinkedList<>();
        if(StringUtils.isNotBlank(user.getDeptChildIds())){
            seatIds = Arrays.stream(user.getDeptChildIds().split(","))
                    .map(Long::valueOf)
                    .collect(Collectors.toList());
        }else{
            //未指定席位则使用所属部门下的所有席位信息
            List<Long> deptIds = new LinkedList<>();
            deptIds.add(user.getDeptId());
            seatIds = this.baseMapper.getSeatIdsByDeptIds(deptIds);
        }
        for (Long seatId : seatIds) {
            if(checkSeatIds.contains(seatId)){
                result = true;
                break;
            }
        }
        return result;
    }

    @Override
    public List<SysDept> getSeatListByDeptId(SysDeptCheckDto sysDept) {
        List<SysDept> checkSeatIds = this.baseMapper.getSeatInfosByDeptIds(sysDept.getDeptIds());
        //添加父部门信息
        checkSeatIds.stream()
                .filter(checkSeatId -> checkSeatId.getParentId() != null)
                .forEach(checkSeatId -> {
                    SysDept sysDeptParent = this.baseMapper.selectById(checkSeatId.getParentId());
                    checkSeatId.setParentDept(sysDeptParent.getDeptName());
                });
           return checkSeatIds;
    }

    @Override
    public List<Long> getUserDeptSeats(SysUser sysUser) {
        //获取用户有权限的所有席位信息
        List<Long> seatIds = new LinkedList<>();
        if(sysUser.getDeptChildId() != null){
            seatIds.add(sysUser.getDeptChildId());
        }else{
            //未指定席位则使用所属部门下的所有席位信息
            List<Long> deptIds = new LinkedList<>();
            deptIds.add(sysUser.getDeptId());
            seatIds = this.baseMapper.getSeatIdsByDeptIds(deptIds);
        }
        return seatIds;
    }

    @Override
    public R updateDept(SysDept dto) {
        SysDept sysDept = this.baseMapper.selectById(dto.getDeptId());
        if(sysDept == null){
            return R.fail("部门/席位信息异常");
        }

        if(dto.getParentId() != null && dto.getParentId() != sysDept.getDeptId()){
            //只能在部门下新增
            SysDept parentDept = this.baseMapper.selectById(sysDept.getParentId());
            if(parentDept == null){
                return R.fail("父节点信息异常");
            }
            if(parentDept.getDeptType().intValue() != 1){
                return R.fail("席位下不允许新增部门/席位");
            }
            sysDept.setParentId(dto.getParentId());
            // 获取父级部门的祖先部门信息，并将当前部门的 ID 加入其中
            String ancestors = parentDept.getAncestors() + "," + sysDept.getParentId();
            // 将fu部门信息赋值给当前部门
            sysDept.setAncestors(ancestors);
        }

        if(dto.getDeptName() != null && !StringUtils.equals(dto.getDeptName(),sysDept.getDeptName())){
            //查询用部门或席位是否存在
            Long count=this.baseMapper.selectCount(new LambdaQueryWrapper<SysDept>()
                    .eq(SysDept::getDeptName,dto.getDeptName())
                    .eq(SysDept::getDelFlag,0)
            );
            if (count>0){
                return R.fail("部门或席位已存在！！！");
            }
            sysDept.setDeptName(dto.getDeptName());
        }

        BeanUtils.copyProperties(dto,sysDept);
        sysDept.setUpdateBy(SecurityUtils.getUsername());
        sysDept.setUpdateTime(LocalDate.now().toString());
        this.updateById(sysDept);

        if(sysDept.getMenuIds() != null && sysDept.getMenuIds().size() > 0){
            SysDeptMenuDto bindDto = new SysDeptMenuDto();
            bindDto.setDeptId(sysDept.getDeptId());
            bindDto.setMenuIds(sysDept.getMenuIds());
            this.menuBind(bindDto);
        }
        return R.ok() ;
    }



    /**
     * 查询部门树结构信息
     *
     * @param dept 部门信息
     * @return 部门树信息集合
     */
    @Override
    public List<TreeSelectDept> selectDeptTree(SysDept dept)
    {
        LambdaQueryWrapper<SysDept> queryWrapper=new LambdaQueryWrapper<>(dept);
        queryWrapper.eq(SysDept::getDeptType,1);
        queryWrapper.eq(SysDept::getDelFlag,0);
        List<SysDept> depts = SpringUtils.getAopProxy(this).list(queryWrapper);
        return buildDeptTreeSelect(depts);
    }

    /**
     * 查询部门树结构信息，所有信息
     *
     * @param dept 部门信息
     * @return 部门树信息集合
     */
    @Override
    public List<SysDept> selectDeptTreeList(SysDept dept)
    {
        List<SysDept> depts = SpringUtils.getAopProxy(this).list(new LambdaQueryWrapper<SysDept>(dept).eq(SysDept::getDelFlag,0));
        return buildDeptTreeAll(depts);
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<SysDept> list, SysDept t)
    {
        // 得到子节点列表
        List<SysDept> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysDept tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysDept> getChildList(List<SysDept> list, SysDept t)
    {
        List<SysDept> tlist = new ArrayList<SysDept>();
        Iterator<SysDept> it = list.iterator();
        while (it.hasNext())
        {
            SysDept n = (SysDept) it.next();
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue())
            {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysDept> list, SysDept t)
    {
        return getChildList(list, t).size() > 0 ? true : false;
    }

    /**
     * 构建前端所需要树结构
     *
     * @param depts 部门列表
     * @return 树结构列表
     */
    @Override
    public List<SysDept> buildDeptTree(List<SysDept> depts)
    {
        List<SysDept> returnList = new ArrayList<SysDept>();
        List<Long> tempList = depts.stream().map(SysDept::getDeptId).collect(Collectors.toList());
        for (SysDept dept : depts)
        {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId()))
            {
                recursionFn(depts, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty())
        {
            returnList = depts;
        }
        return returnList;
    }

    /**
     * 构建前端所需要下拉树结构
     *
     * @param depts 部门列表
     * @return 下拉树结构列表
     */
    @Override
    public List<TreeSelectDept> buildDeptTreeSelect(List<SysDept> depts)
    {
        List<SysDept> deptTrees = buildDeptTree(depts);
        return deptTrees.stream().map(TreeSelectDept::new).collect(Collectors.toList());
    }


    /**
     * 构建前端所有下拉树结构
     *
     * @param depts 部门列表
     * @return 下拉树结构列表
     */
    @Override
    public List<SysDept> buildDeptTreeAll(List<SysDept> depts)
    {
        List<SysDept> deptTrees = buildDeptTree(depts);
        return deptTrees;
    }

}




